/*
 * @功能描述: 
 * @版本: v1.0.0
 * @作者: LuAn
 * @Date: 2021-09-02 06:32:14
 * @LastEditTime: 2021-09-02 07:34:18
 */
#include "bsp_uart.h"
static void _uartx_io_init(UART_Type *uart)
{
  /* 1、初始化IO复用 
     * UART1_RXD -> UART1_TX_DATA
     * UART1_TXD -> UART1_RX_DATA
     * 2、配置UART1_TX_DATA、UART1_RX_DATA的IO属性 
 	   * bit 16:0 HYS关闭
 	   * bit [15:14]: 00 默认100K下拉
 	   * bit [13]: 0 keeper功能
 	   * bit [12]: 1 pull/keeper使能
 	   * bit [11]: 0 关闭开路输出
 	   * bit [7:6]: 10 速度100Mhz
 	   * bit [5:3]: 110 驱动能力R0/6
 	   * bit [0]: 0 低转换率
	 */
  if (uart == UART1)
  {

    IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX, 0); /* 复用为UART1_TX */
    IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX, 0); /* 复用为UART1_RX */

    IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);
    IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
  }
  else if(uart == UART2)
  {
    IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_UART2_TX, 0); /* 复用为UART1_TX */
    IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_UART2_RX, 0); /* 复用为UART1_RX */

    IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_UART2_TX, 0x10B0);
    IOMUXC_SetPinConfig(IOMUXC_UART2_RX_DATA_UART2_RX, 0x10B0);
  }
}

void disable_uart(UART_Type *uart)
{
  uart->UCR1 &= ~(1 << 0);
}
void enable_uart(UART_Type *uart)
{
  uart->UCR1 |= (1 << 0);
}
void uart_softreset(UART_Type *uart)
{
  uart->UCR2 &= ~(1 << 0); /* UCR2的bit0为0，复位UART  	  	*/
  while ((uart->UCR2 & 0x1) == 0)
    ; /* 等待复位完成 					*/
}
void uart_set_baudrate2(UART_Type *base, uint32_t baudrate, uint32_t srcclock_hz)
{
  uint32_t numerator = 0u;   //分子
  uint32_t denominator = 0U; //分母
  uint32_t divisor = 0U;
  uint32_t refFreqDiv = 0U;
  uint32_t divider = 1U;
  uint64_t baudDiff = 0U;
  uint64_t tempNumerator = 0U;
  uint32_t tempDenominator = 0u;

  /* get the approximately maximum divisor */
  numerator = srcclock_hz;
  denominator = baudrate << 4;
  divisor = 1;
  while (denominator != 0)
  {
    divisor = denominator;
    denominator = numerator % denominator;
    numerator = divisor;
  }
  numerator = srcclock_hz / divisor;
  denominator = (baudrate << 4) / divisor;

  /* numerator ranges from 1 ~ 7 * 64k */
  /* denominator ranges from 1 ~ 64k */
  if ((numerator > (UART_UBIR_INC_MASK * 7)) || (denominator > UART_UBIR_INC_MASK))
  {
    uint32_t m = (numerator - 1) / (UART_UBIR_INC_MASK * 7) + 1;
    uint32_t n = (denominator - 1) / UART_UBIR_INC_MASK + 1;
    uint32_t max = m > n ? m : n;
    numerator /= max;
    denominator /= max;
    if (0 == numerator)
    {
      numerator = 1;
    }
    if (0 == denominator)
    {
      denominator = 1;
    }
  }
  divider = (numerator - 1) / UART_UBIR_INC_MASK + 1;

  switch (divider)
  {
  case 1:
    refFreqDiv = 0x05;
    break;
  case 2:
    refFreqDiv = 0x04;
    break;
  case 3:
    refFreqDiv = 0x03;
    break;
  case 4:
    refFreqDiv = 0x02;
    break;
  case 5:
    refFreqDiv = 0x01;
    break;
  case 6:
    refFreqDiv = 0x00;
    break;
  case 7:
    refFreqDiv = 0x06;
    break;
  default:
    refFreqDiv = 0x05;
    break;
  }
  /* Compare the difference between baudRate_Bps and calculated baud rate.
     * Baud Rate = Ref Freq / (16 * (UBMR + 1)/(UBIR+1)).
     * baudDiff = (srcClock_Hz/divider)/( 16 * ((numerator / divider)/ denominator).
     */
  tempNumerator = srcclock_hz;
  tempDenominator = (numerator << 4);
  divisor = 1;
  /* get the approximately maximum divisor */
  while (tempDenominator != 0)
  {
    divisor = tempDenominator;
    tempDenominator = tempNumerator % tempDenominator;
    tempNumerator = divisor;
  }
  tempNumerator = srcclock_hz / divisor;
  tempDenominator = (numerator << 4) / divisor;
  baudDiff = (tempNumerator * denominator) / tempDenominator;
  baudDiff = (baudDiff >= baudrate) ? (baudDiff - baudrate) : (baudrate - baudDiff);

  if (baudDiff < (baudrate / 100) * 3)
  {
    base->UFCR &= ~UART_UFCR_RFDIV_MASK;
    base->UFCR |= UART_UFCR_RFDIV(refFreqDiv);
    base->UBIR = UART_UBIR_INC(denominator - 1); //要先写UBIR寄存器，然后在写UBMR寄存器，3592页
    base->UBMR = UART_UBMR_MOD(numerator / divider - 1);
  }
}
void uart_set_baudrate(UART_Type *uart, uint32_t baudrate)
{
  uart_set_baudrate2(uart, baudrate, UART_SRC_CLK);
}
void uart_init(UART_Type *uart, uint32_t baudrate, void (*uart_io_init)(UART_Type *))
{
  if(uart_io_init == NULL)
  {
    uart_io_init = _uartx_io_init;
  }
  uart_io_init(uart);
  disable_uart(uart);
  uart_softreset(uart);
  UARTx_UCR2_t *ucr2 = (UARTx_UCR2_t *)&uart->UCR2;
  ucr2->IRTS = 1;
  ucr2->PREN = 0;
  ucr2->STPB = 0;
  ucr2->WS = 1;
  ucr2->TXEN = 1;
  ucr2->RXEN = 1;
  uart->UCR3 |= 1 << 2;     // 数据手册有说明，为uart时这个bit必须为1
  uart->UCR1 &= ~(1 << 14); // bit14: 0 关闭自动波特率检测,我们自己设置波特率
  uart_set_baudrate(uart, baudrate);
  enable_uart(uart);
}

void uart_putc(UART_Type *uart, unsigned char c)
{
  while (((uart->USR2 >> 3) & 0X01) == 0)
    ;                    /* 等待上一次发送完成 */
  uart->UTXD = c & 0XFF; /* 发送数据 */
}
void uart_puts(UART_Type *uart, const char *str)
{
  while (*str)
  {
    uart_putc(uart, *str++);
  }
}
int uart_getc(UART_Type *uart)
{
  while ((uart->USR2 & 1) == 0)
  {
    ;
  }
  return uart->URXD;
}

void raise(int sig_nr)
{
}
